package com.example.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.entity.dto.RespExpensesDTO;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.example.common.enums.ResultCodeEnum;
import com.example.common.enums.RoleEnum;
import com.example.entity.*;
import com.example.entity.dto.AddExpensesDTO;
import com.example.exception.CustomException;
import com.example.mapper.ExpensesMapper;
import com.example.service.EmployeeService;
import com.example.service.ExpensesDetailService;
import com.example.service.ExpensesService;
import com.example.service.ProcessingRecordsService;
import com.example.utils.TokenUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.w3c.dom.ls.LSInput;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description TODO
 * @Author dingchunlin
 * @Date 2023/12/27 20:35
 * @Version 1.0.0
 */
@Service
@Slf4j
public class ExpensesServiceImpl extends ServiceImpl<ExpensesMapper, Expenses> implements ExpensesService {

    @Autowired
    private ExpensesMapper expensesMapper;

    @Autowired
    private ExpensesDetailService expensesDetailService;

    @Autowired
    private EmployeeService employeeService;

    @Autowired
    private ProcessingRecordsService processingRecordsService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addExpenses(AddExpensesDTO addExpensesDTO) {
        //判断用户是否输入了报销单信息
        if (ObjectUtil.isEmpty(addExpensesDTO.getExpenses().getExpensesType())){
            throw new CustomException(ResultCodeEnum.EXPESES_DETAIL_ERROR);
        }
        //判断用户是否输入了报销单详细信息
        addExpensesDTO.getDetails().forEach( item ->{
            if (ObjectUtil.isEmpty(item.getAmountType())){
                throw new CustomException(ResultCodeEnum.EXPESES_DETAIL_ERROR);
            }
        });
        //这里的话是声明一个获取总价格的变量
        Double allPrice = new Double(0);
        Employee employee = TokenUtils.getCurrentUser();
        //将数据详细数据进行保存
        Integer departmentId = employee.getDepartmentId();
        //这里是员工进行报销
        if (employee.getRole().equals(RoleEnum.USER.name())) {
            //查询出该部门的部门经理
            Employee res = employeeService.selectByDepartmentIdAndRole(departmentId, RoleEnum.DEPARTMENT_MANAGER.name());

            //首先添加申请单
            Expenses expenses = addExpensesDTO.getExpenses();
            if (ObjectUtil.isNotEmpty(expenses)) {
                //将其他参数进行处理
                expenses.setCreatId(employee.getId());
                expenses.setCreateTime(LocalDateTime.now());
                expenses.setPendingPersonId(res.getId());
                //获取全部价格
                for (ExpensesDetail detail : addExpensesDTO.getDetails()) {
                    allPrice += detail.getAmount();
                }
                //设置价格和审核状态
                expenses.setTotalAmount(allPrice);
                expenses.setStatus("审核中");
                baseMapper.insert(expenses);
            }
            //获取到申请单的id
            Integer expensesId = expenses.getId();
            List<ExpensesDetail> details = addExpensesDTO.getDetails();
            details = details.stream().map( item ->{
                item.setExpenseId(expensesId);
                return item ;
            }).collect(Collectors.toList());
            expensesDetailService.saveBatch(details);
            //添加审核单
            ProcessingRecords processingRecords = new ProcessingRecords();
            processingRecords.setExpenseId(expensesId);
            processingRecords.setHandlerId(res.getId());
            processingRecords.setProcessingType(expenses.getExpensesType());
            processingRecordsService.add(processingRecords);
        }else if (employee.getRole().equals(RoleEnum.DEPARTMENT_MANAGER.name())){//这里是项目经理进行报销
            //查询出总经理的信息
            Employee res = employeeService.selectByDepartmentIdAndRole(0, RoleEnum.GENERAL_MANAGER.name());

            //首先添加申请单
            Expenses expenses = addExpensesDTO.getExpenses();
            if (ObjectUtil.isNotEmpty(expenses)) {
                //将其他参数进行处理
                expenses.setCreatId(employee.getId());
                expenses.setCreateTime(LocalDateTime.now());
                expenses.setPendingPersonId(res.getId());
                //获取全部价格
                for (ExpensesDetail detail : addExpensesDTO.getDetails()) {
                    allPrice += detail.getAmount();
                }
                //设置价格和审核状态
                expenses.setTotalAmount(allPrice);
                expenses.setStatus("审核中");
                baseMapper.insert(expenses);
            }
            //获取到申请单的id
            Integer expensesId = expenses.getId();
            //将报销单的信息进行保存
            List<ExpensesDetail> details = addExpensesDTO.getDetails();
            details = details.stream().map( item ->{
                item.setExpenseId(expensesId);
                return item ;
            }).collect(Collectors.toList());
            expensesDetailService.saveBatch(details);
            //添加审核单
            ProcessingRecords processingRecords = new ProcessingRecords();
            processingRecords.setExpenseId(expensesId);
            processingRecords.setHandlerId(res.getId());
            processingRecords.setProcessingType(expenses.getExpensesType());
            processingRecordsService.add(processingRecords);
        }

    }

    @Override
    public List<String> getExpensesType() {
        List<String> list = new ArrayList<>();
        list.add("交通费");
        list.add("伙食费");
        list.add("购买办公用品等公用费用");
        list.add("项目用车的燃料费");
        list.add("过路桥费");
        list.add("停车费");
        return list;
    }

    @Override
    public PageInfo<Expenses> getExpensesById(Expenses expenses, Integer pageNum, Integer pageSize) {
        Employee token = TokenUtils.getCurrentUser();
        Integer id = token.getId();
        LambdaQueryWrapper<Expenses> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.orderByDesc(Expenses::getId);
        //只查看自己的报销单
        lambdaQueryWrapper.eq(Expenses::getCreatId,id);
        PageHelper.startPage(pageNum, pageSize);
        List<Expenses> list = expensesMapper.selectList(lambdaQueryWrapper);
        list.forEach( item ->{
            Integer creatId = item.getCreatId();
            Employee employee = employeeService.selectById(creatId);
            if (ObjectUtil.isNotEmpty(employee)){
                item.setCreateName(employee.getName());
            }
        });
        return PageInfo.of(list);
    }

    @Override
    public List<Expenses> selectAll(Expenses expenses) {
        LambdaQueryWrapper<Expenses> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Expenses::getStatus,"审核通过");
        List<Expenses> expensesList = expensesMapper.selectList(lambdaQueryWrapper);
        return expensesList;
    }

    @Override
    public AddExpensesDTO getExpensesDataById(Integer expensesId) {
        //创建一个返回对象
        AddExpensesDTO result = new AddExpensesDTO();
        //首先查询出报销单的信息
        Expenses expenses = expensesMapper.selectById(expensesId);
        if (ObjectUtil.isNotEmpty(expenses)){
            result.setExpenses(expenses);
        }
        List<ExpensesDetail> detailsById = expensesDetailService.getDetailsById(expensesId);
        if (ObjectUtil.isNotEmpty(detailsById)){
            result.setDetails(detailsById);
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateExpenses(AddExpensesDTO dto) {
        //声明一个变量用于存储更新后的价格
        Double price = new Double(0);
        //获取报销单的信息
        Expenses expenses = dto.getExpenses();
        //将原来报销单的详细信息进行删除
        expensesDetailService.deleteByExpenseId(expenses.getId());
        //将审核表中的原本记录进行删除
        processingRecordsService.deleteByExpenseId(expenses.getId());
        //获取修改后的详细信息，并且添加报销单的详细信息
        List<ExpensesDetail> details = dto.getDetails();
        for (ExpensesDetail detail : details) {
            detail.setExpenseId(expenses.getId());
            expensesDetailService.saveDetail(detail);
            price += detail.getAmount();
        }
        //这里是将报销单信息进行更新
        if (ObjectUtil.isNotEmpty(expenses)){
            //修改后的审核单重新审核
            expenses.setStatus("审核中");
            expenses.setTotalAmount(price);
            expensesMapper.updateById(expenses);
        }
        //根据员工id查询信息
        Employee employee = employeeService.selectById(expenses.getCreatId());
        //查询出该员工的部门经理信息
        Employee res = employeeService.selectByDepartmentIdAndRole(employee.getDepartmentId(), RoleEnum.DEPARTMENT_MANAGER.name());
        //添加审核单
        ProcessingRecords processingRecords = new ProcessingRecords();
        processingRecords.setExpenseId(expenses.getId());
        processingRecords.setHandlerId(res.getId());
        processingRecords.setProcessingType(expenses.getExpensesType());
        processingRecordsService.add(processingRecords);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteExpensesById(Integer id) {
        //首先将报销单进行删除
        expensesMapper.deleteById(id);
        //将报销单的详细详细进行删除
        expensesDetailService.deleteByExpenseId(id);
        //将审核表中的记录进行删除
        processingRecordsService.deleteByExpenseId(id);
    }

    @Override
    public void updateExpensesById(Expenses expenses) {
        expensesMapper.updateById(expenses);
    }

    @Override
    public Expenses selectById(Integer id) {
        Expenses expenses = expensesMapper.selectById(id);
        Integer creatId = expenses.getCreatId();
        Employee employee = employeeService.selectById(creatId);
        if (ObjectUtil.isNotEmpty(employee)){
            expenses.setCreateName(employee.getName());
        }
        return expenses;
    }

    @Override
    public RespExpensesDTO getDetailExpenseData(Integer id) {
        RespExpensesDTO respExpensesDTO = new RespExpensesDTO();
        //首先查询出这个报销单的信息
        Expenses expenses = selectById(id);
        respExpensesDTO.setExpenses(expenses);
        //根据报销单id查询出详细信息
        List<ExpensesDetail> detailsById = expensesDetailService.getDetailsById(id);
        respExpensesDTO.setDetails(detailsById);
        //通过报销单的id查询审核信息
        ProcessingRecords processingRecords = new ProcessingRecords();
        processingRecords.setExpenseId(id);
        List<ProcessingRecords> processingRecordsList = processingRecordsService.selectAll(processingRecords);
        respExpensesDTO.setRecords(processingRecordsList);
        return respExpensesDTO;
    }
}
